<!DOCTYPE html>
<html CN>







<head>
	
	
	<link rel="stylesheet" href="/css/allinone.min.css"> 

	
	<!-- Global Site Tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-42863699-1"></script>
	<script>
		window.dataLayer = window.dataLayer || [];
		function gtag(){dataLayer.push(arguments);}
		gtag('js', new Date());
		gtag('config', 'UA-42863699-1');
	</script>
	

	<meta charset="utf-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />

	<title>python 和消息机制（二）：Rabbitmq 概念和使用 | Cizixs Write Here</title>

	<meta name="HandheldFriendly" content="True" />
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
	<meta name="generator" content="hexo">
	<meta name="author" content="Cizixs Wu">
	<meta name="description" content="">

	
	<meta name="keywords" content="">
	

	
	<link rel="shortcut icon" href="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg">
	

	
	<meta name="theme-color" content="#3c484e">
	<meta name="msapplication-TileColor" content="#3c484e">
	

	

	

	<meta property="og:site_name" content="Cizixs Write Here">
	<meta property="og:type" content="article">
	<meta property="og:title" content="python 和消息机制（二）：Rabbitmq 概念和使用 | Cizixs Write Here">
	<meta property="og:description" content="">
	<meta property="og:url" content="http://cizixs.com/2015/11/23/rabbitmq-concept-and-usage/">

	
	<meta property="article:published_time" content="2015-11-23T00:11:00+08:00"/> 
	<meta property="article:author" content="Cizixs Wu">
	<meta property="article:published_first" content="Cizixs Write Here, /2015/11/23/rabbitmq-concept-and-usage/" />
	

	
	
	<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
	

	
	<script src="https://cdn.staticfile.org/highlight.js/9.10.0/highlight.min.js"></script>
	

	
	
<link rel="stylesheet" href="/css/prism-base16-ateliersulphurpool.light.css" type="text/css"></head>
<body class="post-template">
    <div class="site-wrapper">
        




<header class="site-header outer" style="z-index: 999">
    <div class="inner">
        
<nav class="site-nav"> 
    <div class="site-nav-left">
        <ul class="nav">
            <li>
                
                <a href="/" title="Home">Home</a>
                
            </li>
            
            
            <li>
                <a href="/about" title="About">About</a>
            </li>
            
            <li>
                <a href="/archives" title="Archives">Archives</a>
            </li>
            
            
        </ul> 
    </div>
    <div class="site-nav-right">
        
<div class="social-links" >
    
    <a class="social-link" title="weibo" href="https://weibo.com/1921727853" target="_blank" rel="noopener">
        <svg viewBox="0 0 1141 1024" xmlns="http://www.w3.org/2000/svg"><path d="M916.48 518.144q27.648 21.504 38.912 51.712t9.216 62.976-14.336 65.536-31.744 59.392q-34.816 48.128-78.848 81.92t-91.136 56.32-94.72 35.328-89.6 18.944-75.264 7.68-51.712 1.536-49.152-2.56-68.096-10.24-78.336-21.504-79.872-36.352-74.24-55.296-59.904-78.848q-16.384-29.696-22.016-63.488t-5.632-86.016q0-22.528 7.68-51.2t27.136-63.488 53.248-75.776 86.016-90.112q51.2-48.128 105.984-85.504t117.248-57.856q28.672-10.24 63.488-11.264t57.344 11.264q10.24 11.264 19.456 23.04t12.288 29.184q3.072 14.336 0.512 27.648t-5.632 26.624-5.12 25.6 2.048 22.528q17.408 2.048 33.792-1.536t31.744-9.216 31.232-11.776 33.28-9.216q27.648-5.12 54.784-4.608t49.152 7.68 36.352 22.016 17.408 38.4q2.048 14.336-2.048 26.624t-8.704 23.04-7.168 22.016 1.536 23.552q3.072 7.168 14.848 13.312t27.136 12.288 32.256 13.312 29.184 16.384zM658.432 836.608q26.624-16.384 53.76-45.056t44.032-64 18.944-75.776-20.48-81.408q-19.456-33.792-47.616-57.344t-62.976-37.376-74.24-19.968-80.384-6.144q-78.848 0-139.776 16.384t-105.472 43.008-72.192 60.416-38.912 68.608q-11.264 33.792-6.656 67.072t20.992 62.976 42.496 53.248 57.856 37.888q58.368 25.6 119.296 32.256t116.224 0.512 100.864-21.504 74.24-33.792zM524.288 513.024q20.48 8.192 38.912 18.432t32.768 27.648q10.24 12.288 17.92 30.72t10.752 39.424 1.536 42.496-9.728 38.912q-8.192 18.432-19.968 37.376t-28.672 35.328-40.448 29.184-57.344 18.944q-61.44 11.264-117.76-11.264t-88.064-74.752q-12.288-39.936-13.312-70.656t16.384-66.56q13.312-27.648 40.448-51.712t62.464-38.912 75.264-17.408 78.848 12.8zM361.472 764.928q37.888 3.072 57.856-18.432t21.504-48.128-15.36-47.616-52.736-16.896q-27.648 3.072-43.008 23.552t-17.408 43.52 9.728 42.496 39.424 21.504zM780.288 6.144q74.752 0 139.776 19.968t113.664 57.856 76.288 92.16 27.648 122.88q0 33.792-16.384 50.688t-35.328 17.408-35.328-14.336-16.384-45.568q0-40.96-22.528-77.824t-59.392-64.512-84.48-43.52-96.768-15.872q-31.744 0-47.104-15.36t-14.336-34.304 18.944-34.304 51.712-15.36zM780.288 169.984q95.232 0 144.384 48.64t49.152 146.944q0 30.72-10.24 43.52t-22.528 11.264-22.528-14.848-10.24-35.84q0-60.416-34.816-96.256t-93.184-35.84q-19.456 0-28.672-10.752t-9.216-23.04 9.728-23.04 28.16-10.752z" /></svg>
    </a>
    

    
    <a class="social-link" title="github" href="https://github.com/cizixs" target="_blank" rel="noopener">
        <svg viewBox="0 0 1049 1024" xmlns="http://www.w3.org/2000/svg"><path d="M524.979332 0C234.676191 0 0 234.676191 0 524.979332c0 232.068678 150.366597 428.501342 358.967656 498.035028 26.075132 5.215026 35.636014-11.299224 35.636014-25.205961 0-12.168395-0.869171-53.888607-0.869171-97.347161-146.020741 31.290159-176.441729-62.580318-176.441729-62.580318-23.467619-60.841976-58.234462-76.487055-58.234463-76.487055-47.804409-32.15933 3.476684-32.15933 3.476685-32.15933 53.019436 3.476684 80.83291 53.888607 80.83291 53.888607 46.935238 79.963739 122.553122 57.365291 152.97411 43.458554 4.345855-33.897672 18.252593-57.365291 33.028501-70.402857-116.468925-12.168395-239.022047-57.365291-239.022047-259.012982 0-57.365291 20.860106-104.300529 53.888607-140.805715-5.215026-13.037566-23.467619-66.926173 5.215027-139.067372 0 0 44.327725-13.906737 144.282399 53.888607 41.720212-11.299224 86.917108-17.383422 131.244833-17.383422s89.524621 6.084198 131.244833 17.383422C756.178839 203.386032 800.506564 217.29277 800.506564 217.29277c28.682646 72.1412 10.430053 126.029806 5.215026 139.067372 33.897672 36.505185 53.888607 83.440424 53.888607 140.805715 0 201.64769-122.553122 245.975415-239.891218 259.012982 19.121764 16.514251 35.636014 47.804409 35.636015 97.347161 0 70.402857-0.869171 126.898978-0.869172 144.282399 0 13.906737 9.560882 30.420988 35.636015 25.205961 208.601059-69.533686 358.967656-265.96635 358.967655-498.035028C1049.958663 234.676191 814.413301 0 524.979332 0z" /></svg>
    </a>
    

    
    <a class="social-link" title="stackoverflow" href="https://stackoverflow.com/users/1925083/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M15 21h-10v-2h10v2zm6-11.665l-1.621-9.335-1.993.346 1.62 9.335 1.994-.346zm-5.964 6.937l-9.746-.975-.186 2.016 9.755.879.177-1.92zm.538-2.587l-9.276-2.608-.526 1.954 9.306 2.5.496-1.846zm1.204-2.413l-8.297-4.864-1.029 1.743 8.298 4.865 1.028-1.744zm1.866-1.467l-5.339-7.829-1.672 1.14 5.339 7.829 1.672-1.14zm-2.644 4.195v8h-12v-8h-2v10h16v-10h-2z"/></svg>
    </a>
    

    

    
    <a class="social-link" title="twitter" href="https://twitter.com/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z"/></svg>

    </a>
    

    
    <a class="social-link" title="instagram" href="https://www.instagram.com/cizixs/" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/></svg>
    </a>
    
    
    
</div>
    </div>
</nav>
    </div>
</header>


<main id="site-main" class="site-main outer" role="main">
    <div class="inner">
        <header class="post-full-header">
            <section class="post-full-meta">
                <time  class="post-full-meta-date" datetime="2015-11-22T16:00:00.000Z" itemprop="datePublished">
                    2015-11-23
                </time>
                
                <span class="date-divider">/</span>
                
                <a href="/categories/blog/">blog</a>&nbsp;&nbsp;
                
                
            </section>
            <h1 class="post-full-title">python 和消息机制（二）：Rabbitmq 概念和使用</h1>
        </header>
        <article class="post-full no-image">
            
            <section class="post-full-content">
                <div id="lightgallery" class="markdown-body">
                    <h2 id="rabbitmq-简介"><a href="#rabbitmq-简介" class="headerlink" title="rabbitmq 简介"></a>rabbitmq 简介</h2><p>Rabbitmq 是 amqp 的 Erlang 实现，也是现在非常流行的一种消息机制。在前面一片文章，我们也提到了消息机制的几个优点：</p>
<ul>
<li>异步（asynchronous）：耗时的工作可以直接丢给消费者，不会阻塞生产者</li>
<li>可扩展（scale）：消息机制的工作模式，在理论上可以让无限的消费者接入进来，使得横向扩展变得异常简单</li>
<li>模块化（modulize）：生产者和消费者不需要知道双方的存在，而且可以使用不同的语言和框架，在物理上位于不同的地方。</li>
</ul>
<p>消息机制当然也有不便之处，比如分布式的架构使得测试和调试变得复杂；因为消费者无法保证能收到任务并完成，并且无法通知生产者（后面会详细讲解这一点），也对很多场景带来麻烦。</p>
<h2 id="rabbitmq-概念和架构"><a href="#rabbitmq-概念和架构" class="headerlink" title="rabbitmq 概念和架构"></a>rabbitmq 概念和架构</h2><p><img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/728b3d6djw1exeozui9f8j20sg0lcdk6.jpg" alt=""></p>
<p>在生产者-消费者模型中，rabbitmq 充当着 broker 的角色。在 rabbitmq 的内部，还有以下的概念：</p>
<ul>
<li><p><strong>Exchanges</strong>：生产者把消息发送到某个 exchange，exchange 的主要工具就是根据一定的规则把消息分发到不同的 queues</p>
</li>
<li><p><strong>Queues</strong>：消息最终被发送到的地方，消费者也是从这里拿消息进行处理</p>
</li>
<li><p><strong>Routing key</strong>：queue 要绑定（binding）到某个 exchange 才有可能接受这个 exchange 转发过来的消息，它们之间的绑定要有 binding key（当 exchange 是 fanout 类型的时候并不需要）。然后每个消息发过来的时候，都会带着 routing key，根据 exchange 的类型，binding key 和 routing key，消息才能正确被转发。</p>
</li>
<li><p><strong>Connection</strong>：生产者和消费者需要连接到 rabbitmq 才能发送和读取消息，这个连接就是 connection，本质上就是 TCP 连接。</p>
</li>
<li><p><strong>Channel</strong>：为了减少网络负载，和减少 TCP 链接数。多个不同的 生产者可以在同一个 TCP 发送消息，只不过在这个 connection 下面独自的 channel 里。你可以把 channel 想象成一根网线里独立的细线。每个 channel 都有自己的  id，用来标识自己。虽然有 connection，不过所有的通信都是在对应的 channel 里进行的。</p>
</li>
<li><p><strong>vhost</strong>：Virtual host，是起到隔离作用的。每一个 vhost 都有自己的 exchanges 和 queues，它们互不影响。不同的应用可以跑在相同的 rabbitmq 上，使用 vhost 把它们隔离开就行。默认情况下，rabbitmq 安装后，默认的 vhost 是 <code>/</code>。 </p>
</li>
</ul>
<h3 id="什么时候定义-queue？"><a href="#什么时候定义-queue？" class="headerlink" title="什么时候定义 queue？"></a>什么时候定义 queue？</h3><p>queue 需要显式地定义，每个 queue 都有一个名字来唯一标示。 生产者和消费者都可以通过 <code>queue.declare</code> 命令来定义 queue，除了命令 queue 还有其他可以配置的属性：</p>
<ul>
<li>exclusive：如果设置成 true，那么只有定义 queue 的应用可以使用</li>
<li>auto-delete：如果设置成 true，当最后一个消费者断开监听的时候，就会自动删除。结合 exclusive 使用，可以建立一个临时的 queue。</li>
</ul>
<p>如果你要定义一个已经存在的 queue，如果两者的名字和属性都相同，rabbitmq 什么都不会做；而如果两者属性不同，就会返回失败。如果你只想检查某个 queue 是否存在，可以把 <code>queue.declare</code> 的 <code>passive</code> 设置成 true，这样当 queue 存在的时候就会返回成功，而 queue 不存在的时候也没有去创建，只是返回失败。</p>
<p>在消费者监听某个 queue 之前，要确保它一定存在，所以消费者要提前 declare 这个 queue。<br>如果生产者发送的消息，没有 queue 可以转发，就会被丢掉。所以生产者在发消息之前也要 declare 这个 queue，除非消息被丢掉是预期的行为。</p>
<h3 id="绑定和转发"><a href="#绑定和转发" class="headerlink" title="绑定和转发"></a>绑定和转发</h3><p>上图中很重要的部分就是 exchange 和 queue 的关联，它决定了消息机制在 rabbitmq 内部怎么转发的。生产者把消息发送到 exchange，然后消息根据一定的规则会被转发到 queues，消费者从 queues 获取消息。</p>
<p>决定消息转发规则的是 exchange 的类型 和 routing key。</p>
<p>queue 和 exchange 也是通过 routing key 绑定的，不过为了不混淆，我们在这篇文章称之为 binding key。每条消息也都有 routing key，当然可能为空，当消息到达 exchange 的时候， rabbitmq 会匹配消息的 routing key 和 binding key，如果匹配，就会转发到对应的 queue，如果不匹配，就会丢弃消息。</p>
<p>下面就看看每种不同的 exchange 类型下面，routing key 是怎么决定转发的：</p>
<ol>
<li><p>exchange type：direct<br> 这种比较简单，当 routing key 和 binding key 相同时，消息就会转发到绑定的 queue。需要注意的是：如果有两个 queue 绑定到一个 exchange，并且 binding key 一样，那么消息会发到两个 queue。默认情况下，rabbitmq 会有 name 为空的 exchange，类型为 direct，当 declare 一个 queue 的时候，默认会绑定到这个 exchange，binding key 是 queue name。</p>
</li>
<li><p>exchange type：fanout<br> 当 exchange 类型是 fanout 的时候，并不需要 binding key，发送到该 exchange 的消息会自动转发给所有绑定的 queues ，也就是说每个 queue 都会收到一份消息。</p>
</li>
<li><p>exchange type：topic<br> 这种类型的 exchange 更复杂，也更灵活，能实现更多有趣的功能。routing key 和原来一样，不过 binding key 的名字中可以使用三种特殊的符号：<code>.</code>、<code>*</code>、<code>#</code>。<code>.</code> 把 binding key 分割成不同的单词（word），<code>*</code>  匹配一个单词，<code>#</code> 可以匹配 0 个或者任意多个单词。<br>举个例子说明一下，可能会清楚一些。如果有一个处理用户多媒体的应用，那么可以发送所有的消息到 <code>media</code> exchange 中，然后 queues 通过 binding key <code>video.upload</code> 和 <code>image.delete</code> 绑定到该 exchange，接受视频上传和图片删除的消息，这和 direct 类型没有区别。后面就有趣了，<code>video.*</code> 接受所有视频有关的消息，<code>*.delete</code> 接受所有删除操作的消息，<code>#</code> 接受所有的消息。</p>
</li>
</ol>
<h3 id="消费者如何获取消息？"><a href="#消费者如何获取消息？" class="headerlink" title="消费者如何获取消息？"></a>消费者如何获取消息？</h3><p>消费者只要建立到某个 rabbitmq 的连接，然后获取到 channel，就可以使用 AMQP 提供的 <code>basic.consume</code> 命令就能获取到某个 queue 的消息。<code>basic.consume</code> 会让消费者一直处于 loop，只要监听的 queue 里有消息，就会取出来来处理。</p>
<p>如果只想读取一条消息，可以使用 <code>basic.get</code>。不要在 <code>while</code> 循环中使用 <code>basic.get</code> 来不断获取消息，而是要直接使用 <code>basic.consume</code>。因为 <code>basic.get</code> 对 rabbitmq 的压力很大，需要每次 subscribe 到 queue，然后 unsubscribe。</p>
<p>如果发送到 queue 的消息，没有消费者来处理，就会一直等待。</p>
<p>还有一个问题需要考虑：如果多个消费者同时监听一个 queue，那么里面的消息会怎么分配呢？默认情况下，rabbitmq 会采用 round-robin 的方式，也就是轮流的机制。如果有三个消费者同时监听已过期 queue，rabbitmq 会把过来的消息一次分发给它们，当然每条消息只会发给一个消费者。</p>
<p>消费者处理了消息，还要向 rabbitmq 发送确认（ack）。确认有两种方式：要么消费者在获取消息之后，显示地发送 <code>basic.ack</code> 消息给 rabbitmq；要么在监听一个 queue 的时候，设置 <code>auto_ack</code> 参数，这样每次消费者收到消息，rabbitmq 就自动认为这个消息已经 ack 了。确认消息的目的是告诉 rabbitmq，这条消息已经处理，可以把它从 queue 里面删除。那么这里还有一个问题：如果没有设置 <code>auto_ack</code> 参数，消费者也没有发送 <code>basic.ack</code> 回去，rabbitmq 会认为这个消息没有被正确处理，会再次发送给其他消费者，同时会把没有 ack 的消费者做下标记，之后不会在发送消息过来。</p>
<p>上面都是消费者要处理消息，如果消费者不愿意处理这个消息呢？只要消息还没有被 ack（如果消息被 ack 了就没有办法啦），就有两个办法可以做到：</p>
<ol>
<li>让消费者从 rabbitmq 断开连接，这时候 rabbitmq 会认为消息没有正确处理，然后交给其他消费者来做</li>
<li>在 rabbitmq 2.0.0 以后，也可以使用 <code>basic.reject</code> 命令来拒绝一条消息。</li>
</ol>
<p>当然如果你确定这个消息，没有办法被其他消费者处理，可以直接 ack，然后不去处理就好。</p>
<h2 id="rabbitmq-权限管理"><a href="#rabbitmq-权限管理" class="headerlink" title="rabbitmq 权限管理"></a>rabbitmq 权限管理</h2><p>理解权限管理之前，先要看一下 rabbitmq 的用户管理。</p>
<ul>
<li>添加用户：<code>rabbitmqctl add_user username password</code></li>
<li>删除用户：<code>rabbitmqctl delete_user username</code></li>
<li>列出所有用户：<code>rabbitmqctl list_users</code></li>
<li>修改某个用户的密码：<code>rabbitmqctl change_password username new_password</code></li>
</ul>
<p>每个用户控制 vhost ，单个用户可以有管理多个 vhost，每个 vhost 的权限都可以单独设置。权限一共有三种：read，write 和 config。</p>
<ul>
<li>read：和消息消费有关的操作，也包括 exchange 的绑定</li>
<li>write：和消息发布有关的操作，也包括 queue 的绑定</li>
<li>configure：queue 和 exchange 的创建和删除</li>
</ul>
<p>rabbitmqctl set_permissions 命令可以设置某个用户的权限，更详细的内容可以参考<a href="https://www.rabbitmq.com/access-control.html" target="_blank" rel="noopener">官方文档</a>。</p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ul>
<li><a href="http://www.amazon.com/RabbitMQ-Action-Distributed-Messaging-Everyone/dp/1935182978" target="_blank" rel="noopener">Rabbitmq in Action</a></li>
</ul>

                </div>
            </section>
        </article>
    </div>
    
<nav class="pagination">
    
    
    <a class="prev-post" title="python 描述器简介" href="/2015/12/31/python-descriptor-introduction/">
        ← python 描述器简介
    </a>
    
    <span class="prev-next-post">•</span>
    
    <a class="next-post" title="HTTP 断点下载功能实现" href="/2015/10/06/http-resume-download/">
        HTTP 断点下载功能实现 →
    </a>
    
    
</nav>

    <div class="inner">
    <!-- Begin Mailchimp Signup Form -->
    <link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">
    <style type="text/css">
    	#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
    	/* Add your own Mailchimp form style overrides in your site stylesheet or in this style block.
    	   We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
    </style>
    <div id="mc_embed_signup">
    <form action="https://cizixs.us7.list-manage.com/subscribe/post?u=2d561b8dea52d73a2e05e6dcb&amp;id=5c710f135b" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
        <div id="mc_embed_signup_scroll">
    	<h2>订阅本博客，第一时间收到文章更新</h2>
    <div class="indicates-required"><span class="asterisk">*</span> indicates required</div>
    <div class="mc-field-group">
    	<label for="mce-EMAIL">邮件地址  <span class="asterisk">*</span>
    </label>
    	<input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
    </div>
    	<div id="mce-responses" class="clear">
    		<div class="response" id="mce-error-response" style="display:none"></div>
    		<div class="response" id="mce-success-response" style="display:none"></div>
    	</div>    <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
        <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_2d561b8dea52d73a2e05e6dcb_5c710f135b" tabindex="-1" value=""></div>
        <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
        </div>
    </form>
    </div>
    <script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script><script type='text/javascript'>(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';}(jQuery));var $mcj = jQuery.noConflict(true);</script>
    <!--End mc_embed_signup-->
    </div>

    <div class="inner">
        <div id="disqus_thread"></div>
    </div>

    
</main>

<div class="t-g-control">
    <div class="gotop">
        <svg class="icon" width="32px" height="32px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M793.024 710.272a32 32 0 1 0 45.952-44.544l-310.304-320a32 32 0 0 0-46.4 0.48l-297.696 320a32 32 0 0 0 46.848 43.584l274.752-295.328 286.848 295.808z" fill="#8a8a8a" /></svg>
    </div>
    <div class="toc-control">
        <svg class="icon toc-icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M779.776 480h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M779.776 672h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M256 288a32 32 0 1 0 0 64 32 32 0 0 0 0-64M392.576 352h387.2a32 32 0 0 0 0-64h-387.2a32 32 0 0 0 0 64M256 480a32 32 0 1 0 0 64 32 32 0 0 0 0-64M256 672a32 32 0 1 0 0 64 32 32 0 0 0 0-64" fill="#8a8a8a" /></svg>
        <svg class="icon toc-close" style="display: none;" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 960c-247.039484 0-448-200.960516-448-448S264.960516 64 512 64 960 264.960516 960 512 759.039484 960 512 960zM512 128.287273c-211.584464 0-383.712727 172.128262-383.712727 383.712727 0 211.551781 172.128262 383.712727 383.712727 383.712727 211.551781 0 383.712727-172.159226 383.712727-383.712727C895.712727 300.415536 723.551781 128.287273 512 128.287273z" fill="#8a8a8a" /><path d="M557.05545 513.376159l138.367639-136.864185c12.576374-12.416396 12.672705-32.671738 0.25631-45.248112s-32.704421-12.672705-45.248112-0.25631l-138.560301 137.024163-136.447897-136.864185c-12.512727-12.512727-32.735385-12.576374-45.248112-0.063647-12.512727 12.480043-12.54369 32.735385-0.063647 45.248112l136.255235 136.671523-137.376804 135.904314c-12.576374 12.447359-12.672705 32.671738-0.25631 45.248112 6.271845 6.335493 14.496116 9.504099 22.751351 9.504099 8.12794 0 16.25588-3.103239 22.496761-9.247789l137.567746-136.064292 138.687596 139.136568c6.240882 6.271845 14.432469 9.407768 22.65674 9.407768 8.191587 0 16.352211-3.135923 22.591372-9.34412 12.512727-12.480043 12.54369-32.704421 0.063647-45.248112L557.05545 513.376159z" fill="#8a8a8a" /></svg>
    </div>
    <div class="gobottom">
        <svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M231.424 346.208a32 32 0 0 0-46.848 43.584l297.696 320a32 32 0 0 0 46.4 0.48l310.304-320a32 32 0 1 0-45.952-44.544l-286.848 295.808-274.752-295.36z" fill="#8a8a8a" /></svg>
    </div>
</div>
<div class="toc-main" style="right: -100%">
    <div class="post-toc">
        <span>TOC</span>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#rabbitmq-简介"><span class="toc-text">rabbitmq 简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#rabbitmq-概念和架构"><span class="toc-text">rabbitmq 概念和架构</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#什么时候定义-queue？"><span class="toc-text">什么时候定义 queue？</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#绑定和转发"><span class="toc-text">绑定和转发</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#消费者如何获取消息？"><span class="toc-text">消费者如何获取消息？</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#rabbitmq-权限管理"><span class="toc-text">rabbitmq 权限管理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#参考资料"><span class="toc-text">参考资料</span></a></li></ol>
    </div>
</div>



        

<aside class="read-next outer">
    <div class="inner">
        <div class="read-next-feed">
            
            

<article class="read-next-card"  style="background-image: url(https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxcn9ft3j318w0txdo6.jpg)"  >
  <header class="read-next-card-header">
    <small class="read-next-card-header-sitetitle">&mdash; Cizixs Write Here &mdash;</small>
    <h3 class="read-next-card-header-title">Recent Posts</h3>
  </header>
  <div class="read-next-divider">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M13 14.5s2 3 5 3 5.5-2.463 5.5-5.5S21 6.5 18 6.5c-5 0-7 11-12 11C2.962 17.5.5 15.037.5 12S3 6.5 6 6.5s4.5 3.5 4.5 3.5"/>
    </svg>
  </div>
  <div class="read-next-card-content">
    <ul>
      
      
      
      <li>
        <a href="/2018/08/26/what-is-istio/">什么是 istio</a>
      </li>
      
      
      
      <li>
        <a href="/2018/08/25/knative-serverless-platform/">serverless 平台 knative 简介</a>
      </li>
      
      
      
      <li>
        <a href="/2018/06/25/kubernetes-resource-management/">kubernetes 资源管理概述</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/24/use-prometheus-and-grafana-to-monitor-linux-machine/">使用 promethues 和 grafana 监控自己的 linux 机器</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/13/linux-udp-packet-drop-debug/">linux 系统 UDP 丢包问题分析思路</a>
      </li>
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    </ul>
  </div>
  <footer class="read-next-card-footer">
    <a href="/archives">  MORE  → </a>
  </footer>
</article>


            
            
            
        </div>
    </div>
</aside>


<footer class="site-footer outer">

	<div class="site-footer-content inner">
		<section class="copyright">
			<a href="/" title="Cizixs Write Here">Cizixs Write Here</a>
			&copy; 2019
		</section>
		<nav class="site-footer-nav">
			
            <a href="https://hexo.io" title="Hexo" target="_blank" rel="noopener">Hexo</a>
            <a href="https://github.com/xzhih/hexo-theme-casper" title="Casper" target="_blank" rel="noopener">Casper</a>
        </nav>
    </div>
</footer>






<div class="floating-header" >
	<div class="floating-header-logo">
        <a href="/" title="Cizixs Write Here">
			
                <img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg" alt="Cizixs Write Here icon" />
			
            <span>Cizixs Write Here</span>
        </a>
    </div>
    <span class="floating-header-divider">&mdash;</span>
    <div class="floating-header-title">python 和消息机制（二）：Rabbitmq 概念和使用</div>
    <progress class="progress" value="0">
        <div class="progress-container">
            <span class="progress-bar"></span>
        </div>
    </progress>
</div>
<script>
   $(document).ready(function () {
    var progressBar = document.querySelector('progress');
    var header = document.querySelector('.floating-header');
    var title = document.querySelector('.post-full-title');
    var lastScrollY = window.scrollY;
    var lastWindowHeight = window.innerHeight;
    var lastDocumentHeight = $(document).height();
    var ticking = false;

    function onScroll() {
        lastScrollY = window.scrollY;
        requestTick();
    }
    function requestTick() {
        if (!ticking) {
            requestAnimationFrame(update);
        }
        ticking = true;
    }
    function update() {
        var rect = title.getBoundingClientRect();
        var trigger = rect.top + window.scrollY;
        var triggerOffset = title.offsetHeight + 35;
        var progressMax = lastDocumentHeight - lastWindowHeight;
            // show/hide floating header
            if (lastScrollY >= trigger + triggerOffset) {
                header.classList.add('floating-active');
            } else {
                header.classList.remove('floating-active');
            }
            progressBar.setAttribute('max', progressMax);
            progressBar.setAttribute('value', lastScrollY);
            ticking = false;
        }

        window.addEventListener('scroll', onScroll, {passive: true});
        update();

        // TOC
        var width = $('.toc-main').width();
        $('.toc-control').click(function () {
            if ($('.t-g-control').css('width')=="50px") {
                if ($('.t-g-control').css('right')=="0px") {
                    $('.t-g-control').animate({right: width}, "slow");
                    $('.toc-main').animate({right: 0}, "slow");
                    toc_icon()
                } else {
                    $('.t-g-control').animate({right: 0}, "slow");
                    $('.toc-main').animate({right: -width}, "slow");
                    toc_icon()
                }
            } else {
                if ($('.toc-main').css('right')=="0px") {
                    $('.toc-main').slideToggle("fast", toc_icon());
                } else {
                    $('.toc-main').css('right', '0px');
                    toc_icon()
                }
            }
        })

        function toc_icon() {
            if ($('.toc-icon').css('display')=="none") {
                $('.toc-close').hide();
                $('.toc-icon').show();
            } else {
                $('.toc-icon').hide();
                $('.toc-close').show();
            }
        }

        $('.gotop').click(function(){
            $('html,body').animate({scrollTop:$('.post-full-header').offset().top}, 800);
        });
        $('.gobottom').click(function () {
            $('html,body').animate({scrollTop:$('.pagination').offset().top}, 800);
        });

        // highlight
        // https://highlightjs.org
        $('pre code').each(function(i, block) {
            hljs.highlightBlock(block);
        });
        $('td.code').each(function(i, block) {
            hljs.highlightBlock(block);
        });

        console.log("this theme is from https://github.com/xzhih/hexo-theme-casper")
    });
</script>



<link rel="stylesheet" href="https://cdn.staticfile.org/lightgallery/1.3.9/css/lightgallery.min.css">



<script src="https://cdn.staticfile.org/lightgallery/1.3.9/js/lightgallery.min.js"></script>


<script>
	$(function () {
		var postImg = $('#lightgallery').find('img');
		postImg.addClass('post-img');
		postImg.each(function () {
			var imgSrc = $(this).attr('src');
			$(this).attr('data-src', imgSrc);
		});
		$('#lightgallery').lightGallery({selector: '.post-img'});
	});
</script>



<script>

/**
*  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
*  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/

var disqus_config = function () {
this.page.url = 'http://cizixs.com/2015/11/23/rabbitmq-concept-and-usage/';  // Replace PAGE_URL with your page's canonical URL variable
this.page.identifier = 'http://cizixs.com/2015/11/23/rabbitmq-concept-and-usage/'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};

(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://cizixs.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
                            


    </div>
</body>
</html>
